<template>
  <div class="grid">
    <el-card>
      <template #header>
        <div class="card-header">
          <span>账户列表</span>
          <el-input
            v-model="search"
            placeholder="快速筛选"
            clearable
            size="small"
            style="width: 200px"
            @input="filterUsers"
          >
            <template #prefix>
              <el-icon><Search /></el-icon>
            </template>
          </el-input>
        </div>
      </template>
      <el-table
        :data="filteredUsers"
        height="420"
        highlight-current-row
        @current-change="handleUserChange"
        :current-row-key="selectedUserId"
        row-key="id"
        v-loading="loading"
      >
        <el-table-column prop="real_name" label="姓名" width="140" />
        <el-table-column prop="username" label="用户名" width="140" />
        <el-table-column label="状态" width="90">
          <template #default="{ row }">
            <el-tag size="small" :type="row.status === 1 ? 'success' : 'info'">
              {{ row.status === 1 ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="已授权角色" min-width="200">
          <template #default="{ row }">
            <el-tag v-for="role in getUserRoleNames(row.id)" :key="role" type="info" size="small">
              {{ role }}
            </el-tag>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <el-card>
      <template #header>
        <div class="card-header">
          <span>角色授权</span>
          <el-tag v-if="currentUser" type="primary" effect="plain">
            当前：{{ currentUser.real_name }}
          </el-tag>
        </div>
      </template>

      <el-alert v-if="!currentUser" title="请选择需要授权的账户" type="info" show-icon />
      <div v-else class="auth-form">
        <el-form label-width="100px">
          <el-form-item label="角色选择">
            <el-select v-model="selectedRoleIds" multiple placeholder="请选择角色" collapse-tags>
              <el-option v-for="role in roles" :key="role.id" :label="role.role_name" :value="role.id" />
            </el-select>
          </el-form-item>
        </el-form>
        <div class="actions">
          <el-button type="primary" :loading="saving" @click="handleSave">保存授权</el-button>
          <el-button @click="resetSelection">重置</el-button>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Search } from '@element-plus/icons-vue'
import { getUserList, getRoleList, getUserRoleList, createUserRole, deleteUserRole } from '@/api/system'
import type { Role, User, UserRole } from '@/types/system'

const users = ref<User[]>([])
const roles = ref<Role[]>([])
const assignments = ref<UserRole[]>([])
const filteredUsers = ref<User[]>([])
const search = ref('')
const selectedUserId = ref<number | null>(null)
const selectedRoleIds = ref<number[]>([])
const loading = ref(false)
const saving = ref(false)

const currentUser = computed(() => users.value.find((item) => item.id === selectedUserId.value) || null)

const loadData = async () => {
  loading.value = true
  try {
    const [userRes, roleRes, assignmentRes] = await Promise.all([
      getUserList({ limit: 200 }),
      getRoleList({ limit: 200 }),
      getUserRoleList({ limit: 2000 })
    ])
    users.value = userRes.items
    filteredUsers.value = users.value
    roles.value = roleRes.items
    assignments.value = assignmentRes.items
    if (!selectedUserId.value && users.value.length > 0) {
      selectedUserId.value = users.value[0]!.id
    }
    syncSelection()
  } catch (error: any) {
    ElMessage.error(error?.message || '加载账户授权数据失败')
  } finally {
    loading.value = false
  }
}

const filterUsers = () => {
  const keyword = search.value.trim().toLowerCase()
  filteredUsers.value = keyword
    ? users.value.filter(
        (item) =>
          item.real_name.toLowerCase().includes(keyword) ||
          item.username.toLowerCase().includes(keyword)
      )
    : users.value
}

const getUserRoleNames = (userId: number) => {
  const roleMap = new Map(roles.value.map((role) => [role.id, role.role_name]))
  return assignments.value
    .filter((item) => item.user_id === userId)
    .map((item) => roleMap.get(item.role_id))
    .filter((name): name is string => Boolean(name))
}

const syncSelection = () => {
  if (!selectedUserId.value) {
    selectedRoleIds.value = []
    return
  }
  selectedRoleIds.value = assignments.value
    .filter((item) => item.user_id === selectedUserId.value)
    .map((item) => item.role_id)
}

const handleUserChange = (row: User | undefined) => {
  if (!row) return
  selectedUserId.value = row.id
  syncSelection()
}

const resetSelection = () => {
  syncSelection()
}

const handleSave = async () => {
  if (!selectedUserId.value) return
  saving.value = true
  try {
    const existing = assignments.value.filter((item) => item.user_id === selectedUserId.value)
    const existingRoleIds = new Set(existing.map((item) => item.role_id))
    const targetRoleIds = new Set(selectedRoleIds.value)

    const toAdd = selectedRoleIds.value.filter((id) => !existingRoleIds.has(id))
    const toRemove = existing.filter((item) => !targetRoleIds.has(item.role_id))

    await Promise.all([
      ...toAdd.map((role_id) => createUserRole({ user_id: selectedUserId.value!, role_id })),
      ...toRemove.map((item) => deleteUserRole(item.id))
    ])

    ElMessage.success('授权已更新')
    const freshAssignments = await getUserRoleList({ limit: 2000 })
    assignments.value = freshAssignments.items
    syncSelection()
  } catch (error: any) {
    ElMessage.error(error?.message || '保存失败')
  } finally {
    saving.value = false
  }
}

onMounted(loadData)
</script>

<style scoped lang="scss">
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--spacing-lg);
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.auth-form {
  padding-top: var(--spacing-md);
}

.actions {
  display: flex;
  gap: var(--spacing-sm);
}

@media (max-width: 992px) {
  .grid {
    grid-template-columns: 1fr;
  }
}
</style>
